#include <assert.h>
#include <iostream>

#include "disk.h"
#include "common.h"


namespace VirtualR {

Disk::Disk(std::string dir) : level_zero_(dir + "/" + LEVEL_NAME[0]) {
  dir_ = dir;
  if (!access(dir.c_str(), 0)) {
    mkdir(dir.c_str(), S_IRWXU);
  }
  std::string tmp_file = dir_ + "/meta";
  FILE *file;
  if (!(file = fopen(tmp_file.c_str(), "r"))) {
    // 不存在
    file = fopen(tmp_file.c_str(), "w+");
    if (file == NULL) {
      std::cout << "can't create file: " << tmp_file << std::endl;
      assert(false);
    }
    no_ = 0;
    dump_to_disk();
  } else {
    fread(&no_, sizeof(uint64_t), 1, file);
  }
  fclose(file);
  
  for (uint32_t i = 1; i < TOTAL_LEVEL; i++) {
    level_non_zero_vec_.emplace_back(LevelNonZero(dir_ + "/" + LEVEL_NAME[i]));
  }
}

std::pair<bool, std::string> Disk::search(std::string key) {
  std::pair<bool, std::string> res;
  res = level_zero_.search(key);
  if (res.first == true) {
    return res;
  }

  for (uint32_t i = 0; !res.first && i < level_non_zero_vec_.size(); i++) {
    res = level_non_zero_vec_[i].search(key);
  }
  if (res.first) {
    success_count_++;
  } else {
    fail_count_++;
  }
  return res;
}

bool Disk::add(SkipList &mem) {
  level_zero_.add(mem, ++no_);
  if (level_zero_.size() > LEVEL_SIZE[0]) {
    level_non_zero_vec_[0].merge(level_zero_.get_all_entry(), ++no_);
  }
  for (uint32_t i = 1; i + 1 < TOTAL_LEVEL; i++) {
    if (level_non_zero_vec_[i].size() >= LEVEL_SIZE[i]) {
      level_non_zero_vec_[i + 1].merge(level_non_zero_vec_[i].get_entry(), ++no_);
    }
  }
  dump_to_disk();
  return true;
}

void Disk::clear() {
  level_zero_.clear();
  for (uint32_t i = 0; i < level_non_zero_vec_.size(); i++) {
    level_non_zero_vec_[i].clear();
  }
  no_ = 0;
  dump_to_disk();
}

void Disk::dump_to_disk() {
  std::string tmp = dir_ + "/meta";
  FILE *file = fopen(tmp.c_str(), "w");
  auto size_d = 0;
  size_d = fwrite(&no_, sizeof(uint64_t), 1, file);
  if (size_d != 1) {
    std::cout << "Disk::dump_to_disk write no error" << std::endl;
    assert(false);
  }
  fclose(file);
}
}